package com.cryptoneedle.garden.service.garden.doris;


import cn.hutool.v7.core.bean.BeanUtil;
import com.bubbles.engine.data.core.repository.BaseRepository;
import com.bubbles.engine.data.core.service.BaseService;
import com.cryptoneedle.garden.dto.DorisMetadataTable;
import com.cryptoneedle.garden.dto.DorisMetadataTableStorage;
import com.cryptoneedle.garden.entity.garden.doris.DorisTable;
import com.cryptoneedle.garden.entity.garden.doris.DorisTableScript;
import com.cryptoneedle.garden.enums.DorisTableModel;
import com.cryptoneedle.garden.key.TableKey;
import com.cryptoneedle.garden.repository.doris.DorisMetadataRepository;
import com.cryptoneedle.garden.repository.garden.doris.DorisTableRepository;
import com.cryptoneedle.garden.service.crud.garden.doris.*;
import com.cryptoneedle.garden.service.util.BucketUtil;
import com.google.common.collect.Maps;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Map;

/**
 * <p>description: Doris Table </p>
 *
 * @author CryptoNeedle
 * @date 2025-09-25
 */
@Service
@Slf4j
public class DorisTableService extends BaseService<DorisTable, TableKey> {

    @Resource
    private DorisTableRepository dorisTableRepository;

    @Override
    public BaseRepository<DorisTable, TableKey> getRepository() {
        return this.dorisTableRepository;
    }

    @Autowired
    private AddDorisService add;
    @Autowired
    private DeleteDorisService delete;
    @Autowired
    private FoundDorisService select;
    @Autowired
    private PatchDorisService patch;
    @Autowired
    private SaveDorisService save;

    @Resource
    private DorisMetadataRepository dorisMetadataRepository;

    public List<DorisTable> syncDorisTable(String catalogName, String databaseName) {
        // 查询存储信息
        List<DorisMetadataTableStorage> dorisMetadataTableStorages = dorisMetadataRepository.showShowData(catalogName, databaseName);
        Map<String, DorisMetadataTableStorage> storageMap = Maps.uniqueIndex(dorisMetadataTableStorages, DorisMetadataTableStorage::getTableName);

        // 查询所有
        List<DorisTable> originList = select.dorisTables(catalogName, databaseName);
        Map<String, DorisTable> originMap = Maps.uniqueIndex(originList, DorisTable::tableKeyString);

        // 待同步数据
        List<DorisTable> dealList = dorisMetadataRepository.showTableStatusFrom(catalogName, databaseName)
                .stream()
                .map(deal -> BeanUtil.copyProperties(deal, DorisTable.class))
                .toList();
        Map<String, DorisTable> dealMap = Maps.uniqueIndex(dealList, DorisTable::tableKeyString);
        // 补充数据
        List<DorisMetadataTable> dealEnhanceList = dorisMetadataRepository.showFullTablesFrom(catalogName, databaseName);
        Map<String, DorisMetadataTable> dealEnhance = Maps.uniqueIndex(dealEnhanceList, DorisMetadataTable::getKey);
        dealList.forEach(deal -> {
            DorisMetadataTable enhance = dealEnhance.get(deal.tableKeyString());
            if (enhance != null) {
                deal.setTableType(enhance.getTableType());
                deal.setStorageFormat(enhance.getStorageFormat());
                deal.setInvertedIndexStorageFormat(enhance.getInvertedIndexStorageFormat());
            }

            DorisMetadataTableStorage storage = storageMap.get(deal.getTableName());
            if (storage != null) {
                deal.setStorgeSize(storage.getSize());
                deal.setReplicaCount(storage.getReplicaCount());
                deal.setRemoteSize(storage.getRemoteSize());
                deal.setSizeFormatMegaBytes(storage.getSizeFormatMegaBytes());
                if (storage.getSizeFormatMegaBytes() != null) {
                    Integer bucket = BucketUtil.estimateBucket(storage.getSizeFormatMegaBytes().doubleValue(), 1.0);
                    deal.setEstimateBucket(bucket);
                }
            }

            // 表创建语句
            DorisTableScript createTable = dorisMetadataRepository.showCreateTable(catalogName, databaseName, deal.getTableName());
            if (createTable != null) {
                String createTableSql = createTable.getScript();
                if (StringUtils.isNotEmpty(createTableSql)) {
                    //deal.setCreateTableSql(createTableSql);
                    deal.setBucket(StringUtils.substringBetween(createTableSql, "BUCKETS ", "\n"));
                    if (StringUtils.contains(createTableSql, "AGGREGATE KEY")) {
                        deal.setTableModel(DorisTableModel.AGGREGATE_KEY);
                    }
                    if (StringUtils.contains(createTableSql, "DUPLICATE KEY")) {
                        deal.setTableModel(DorisTableModel.DUPLICATE_KEY);
                    }
                    if (StringUtils.contains(createTableSql, "UNIQUE KEY")) {
                        deal.setTableModel(DorisTableModel.UNIQUE_KEY);
                    }
                    deal.setPartition(StringUtils.contains(createTableSql, "PARTITION BY"));

                    save.save(createTable);
                }
            }
        });

        // 新增数据
        List<DorisTable> addList = dealList.stream().filter(deal -> !originMap.containsKey(deal.tableKeyString())).toList();

        // 移除数据
        List<DorisTable> removeList = originList.stream().filter(item -> !dealMap.containsKey(item.tableKeyString())).toList();

        // 保存数据
        List<DorisTable> saveList = originList
                .stream()
                .filter(origin -> dealMap.containsKey(origin.tableKeyString()))
                .peek(origin -> {
                    DorisTable deal = dealMap.get(origin.tableKeyString());
                    origin.setCatalogName(deal.getCatalogName())
                            .setDatabaseName(deal.getDatabaseName())
                            .setTableName(deal.getTableName())
                            .setTableType(deal.getTableType())
                            .setTableModel(deal.getTableModel())
                            .setStorageFormat(deal.getStorageFormat())
                            .setInvertedIndexStorageFormat(deal.getInvertedIndexStorageFormat())
                            .setEngine(deal.getEngine())
                            .setTableRows(deal.getTableRows())
                            .setAvgRowLength(deal.getAvgRowLength())
                            .setDataLength(deal.getDataLength())
                            .setCreateTime(deal.getCreateTime())
                            .setUpdateTime(deal.getUpdateTime())
                            .setTableCollation(deal.getTableCollation())
                            .setTableComment(deal.getTableComment())
                            .setPartition(deal.getPartition())
                            //.setCreateTableSql(deal.getCreateTableSql())
                            .setBucket(deal.getBucket())
                            .setEstimateBucket(deal.getEstimateBucket())
                            .setStorgeSize(deal.getStorgeSize())
                            .setReplicaCount(deal.getReplicaCount())
                            .setRemoteSize(deal.getRemoteSize())
                            .setSizeFormatMegaBytes(deal.getSizeFormatMegaBytes());
                }).toList();

        add.dorisTables(addList);
        save.dorisTables(saveList);
        delete.dorisTables(removeList);

        return select.dorisTables(catalogName, databaseName);
    }
}